#pragma once

#include "pch.h"

#ifdef _WIN32
#include <Windows.h>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#pragma comment(lib, "legacy_stdio_definitions.lib")
#endif

#ifdef __linux__
#include <GLFW/glfw3.h>
#include <GLES3/gl3.h>
#endif // linux


#ifdef WIN32
inline std::string GetShaderType(int type)
{
	switch (type)
	{
	case GL_VERTEX_SHADER:
		return "Vertex";
	case GL_FRAGMENT_SHADER:
		return "Fragment";
	case GL_GEOMETRY_SHADER:
		return "Geometry";
	case GL_COMPUTE_SHADER:
		return "Compute";
	default:
		break;
	}
	return "Unknown";
}
#else
inline std::string GetShaderType(int type)
{
	switch (type)
	{
	case GL_VERTEX_SHADER:
		return "Vertex";
	case GL_FRAGMENT_SHADER:
		return "Fragment";
	default:
		break;
	}
	return "Unknown";
}


#endif // DEBUG


inline bool checkCompileErrors(unsigned int shader, std::string type)
{
	GLint success;
	GLchar infoLog[1024];
	if (type != "PROGRAM")
	{
		glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
		if (!success)
		{
			glGetShaderInfoLog(shader, 1024, NULL, infoLog);
			LOGE("ERROR::SHADER_COMPILATION_ERROR of type: %s \n %s", type.c_str(), infoLog);
		}
	}
	else
	{
		glGetProgramiv(shader, GL_LINK_STATUS, &success);
		if (!success)
		{
			glGetProgramInfoLog(shader, 1024, NULL, infoLog);
			LOGE("ERROR::PROGRAM_LINKING_ERROR of type: %s \n %s", type.c_str(), infoLog);
		}
	}
	return success;
}

inline std::string GetContext(std::string path)
{
	std::ifstream ifs;
	ifs.open(path);
	if (!ifs.is_open())
	{
		LOGI("cannot open file %s \n", path.c_str());
		ifs.close();
		return "";
	}

	std::string text= std::string((std::istreambuf_iterator<char>(ifs)),
		(std::istreambuf_iterator<char>()));

	ifs.close();

	return text;
}

#define ThrowIfFailed(X) {if(!X) return false;}

struct GLFWConfig
{
	int width = 800;
	int height = 600;
	int posX = 200;
	int posY = 200;
	char title[64] = "OpenGL GLFW Example";
};
